/*
 * SetupDatabase.java
 *
 * Created on 06 April 2003, 06:16
 * Copyright (C) 2003, Velocityme Partnership
 */

package com.velocityme.utility;

import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject; 

import com.velocityme.interfaces.*;
import com.velocityme.session.KeySessionBean;
import com.velocityme.valueobjects.*;
import com.velocityme.utility.InvalidKeyException;
import com.velocityme.utility.PermissionDeniedException;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Iterator;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.naming.NamingException;

/**
 *
 * @author  Robert Crida Work
 */
public class SetupDatabase {
    
    private KeySession m_key;
    private boolean m_proceed;
    private RemoteClientSession m_cs;
    
    public SetupDatabase(String username, String password) {
        try {
            SetupSession setupSession = SetupSessionUtil.getHome().create();
            m_proceed = setupSession.setupSystemNew(username, password);
            if (m_proceed)
                m_cs = RemoteClientSessionUtil.getHome().create();
            setupSession.remove();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
    
    public boolean getProceed() {
        return m_proceed;
    }
    
    public boolean login(String username, String password) throws RemoteException, NamingException, CreateException {
        m_key = KeySessionUtil.getHome().create();
        return m_key.getLocal().login(username, password, getClass().getPackage().getImplementationVersion(), "SetupDatabase") == KeySessionBean.LOGIN_SUCCESS;
    }
    
    public void logout() throws RemoteException {
        m_key.logout();
    }
    
    public void setupProjects() throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);
        NodePK rootNodePK = m_cs.findNodeRoot(m_key);

        NodeValue projectNodeValue = new NodeValue(id, "Project", "The root node for all projects", "Node", "SystemNode");
        NodePK projectNodePK = m_cs.nodeCreate(m_key, rootNodePK, projectNodeValue, "SystemNode");
    }
    
    public void setupSystemConfig(String p_username) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);
        NodePK rootNodePK = m_cs.findNodeRoot(m_key);
                
        NodeValue systemConfigNodeValue = new NodeValue(id, "System Configuration", "Branch of the tree for system configuration", "Node", "SystemNode");
        NodePK systemConfigNodePK = m_cs.nodeCreate(m_key, rootNodePK, systemConfigNodeValue, "SystemNode");
        setupOrganisations(systemConfigNodePK);
        setupUsers(p_username, systemConfigNodePK);
        setupGroups(systemConfigNodePK);
        setupTaskTypes(systemConfigNodePK);
        setupRoles(systemConfigNodePK);
        setupContactDetailTypes(systemConfigNodePK);
        setupSystemProperties(systemConfigNodePK);
        setupLicenceManagement(systemConfigNodePK);
        setupLoginHistory(systemConfigNodePK);
        setupDirectory(systemConfigNodePK);
    }
    
    public void setupOrganisations(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue organisationNodeValue = new NodeValue(id, "Setup Organisations", "The root node for all organisations", "Node", "SystemNode");
        NodePK organisationNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, organisationNodeValue, "SystemNode");
        
        // move default organisation to the correct place
        NodePK defaultOrganisationNodePK = null;
        Collection organisationValues = m_cs.getAllOrganisationValues(m_key);
        Iterator i = organisationValues.iterator();
        while(i.hasNext()) {
            OrganisationValue organisationValue = (OrganisationValue)i.next();
            if (organisationValue.getContactableValue().getNodeValue().getName().equals("Default Organisation")) {
                defaultOrganisationNodePK = organisationValue.getContactableValue().getNodeValue().getPrimaryKey();
                m_cs.moveChildNode(m_key, organisationNodePK, organisationValue.getContactableValue().getNodeValue().getPrimaryKey());
            }
        }
        
        // move default department to the correct place
        NodePK defaultDepartmentNodePK = null;
        Collection departmentValues = m_cs.getAllDepartmentValues(m_key);
        i = departmentValues.iterator();
        while(i.hasNext()) {
            DepartmentValue departmentValue = (DepartmentValue)i.next();
            if (departmentValue.getContactableValue().getNodeValue().getName().equals("Default Department")) {
                defaultDepartmentNodePK = departmentValue.getContactableValue().getNodeValue().getPrimaryKey();
                m_cs.moveChildNode(m_key, defaultOrganisationNodePK, departmentValue.getContactableValue().getNodeValue().getPrimaryKey());
            }
        }
        
        // move default person to the correct place
        Collection personValues = m_cs.getAllPersonValues(m_key);
        i = personValues.iterator();
        while(i.hasNext()) {
            PersonValue personValue = (PersonValue)i.next();
            if (personValue.getContactableValue().getNodeValue().getName().equals("Default Person"))
                m_cs.moveChildNode(m_key, defaultDepartmentNodePK, personValue.getContactableValue().getNodeValue().getPrimaryKey());
        }
    }
    
    public void setupUsers(String username, NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue userNodeValue = new NodeValue(id, "Setup Users", "The root node for all users", "Node", "SystemNode");
        NodePK userNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, userNodeValue, "SystemNode");
        
        // move default user to the correct place
        Collection userValues = m_cs.getAllUserValues(m_key);
        Iterator i = userValues.iterator();
        while(i.hasNext()) {
            UserValue userValue = (UserValue)i.next();
            if (userValue.getNodeValue().getName().equals(username))
                m_cs.moveChildNode(m_key, userNodePK, userValue.getNodeValue().getPrimaryKey());
        }
    }
    
    public void setupGroups(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue userNodeValue = new NodeValue(id, "Setup Groups", "The root node for all groups", "Node", "SystemNode");
        NodePK userNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, userNodeValue, "SystemNode");
    }
    
    public void setupTaskTypes(NodePK systemConfigNodePK) throws RemoteException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue taskTypeNodeValue = new NodeValue(id, "Setup Task Types", "The root node for all task types", "Node", "SystemNode");
        NodePK taskTypeNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, taskTypeNodeValue, "SystemNode");
        
        NodeValue stateNodeValue = new NodeValue(id, "Setup States", "The root node for all states", "Node", "SystemNode");
        NodePK stateNodePK = m_cs.nodeCreate(m_key, taskTypeNodePK, stateNodeValue, "SystemNode");
        
        NodeValue statusNodeValue = new NodeValue(id, "Setup Statuses", "The root node for all statuses", "Node", "SystemNode");
        NodePK statusNodePK = m_cs.nodeCreate(m_key, taskTypeNodePK, statusNodeValue, "SystemNode");
        
        StateValue startStateValue = new StateValue(id, Boolean.FALSE);
        startStateValue.setNodeValue(new NodeValue(id, "Start State", "Entry point for all state machines", "State", "State"));
        StatePK startStatePK = m_cs.stateCreate(m_key, stateNodePK, startStateValue);
        startStateValue = m_cs.getStateValue(m_key, startStatePK);
        
        StatusValue defaultStatusValue = new StatusValue(id);
        defaultStatusValue.setNodeValue(new NodeValue(id, "Default Status", "Default status for all state machines", "Status", "Status"));
        StatusPK defaultStatusPK = m_cs.statusCreate(m_key, statusNodePK, defaultStatusValue);
        
        TaskStateMachineValue defaultTaskTypeValue = new TaskStateMachineValue(id);
        defaultTaskTypeValue.setNodeValue(new NodeValue(id, "Default", "Default Task Type, should be changed during moderation", "TaskStateMachine", "TaskStateMachine"));
        TaskStateMachinePK defaultTaskTypePK = m_cs.taskStateMachineCreate(m_key, taskTypeNodePK, defaultTaskTypeValue);

        StateValue pendingStateValue = new StateValue(id, Boolean.FALSE);
        pendingStateValue.setNodeValue(new NodeValue(id, "Pending", "The task has been created but not yet started.", "State", "State"));
        StatePK pendingStatePK = m_cs.stateCreate(m_key, stateNodePK, pendingStateValue);
        pendingStateValue = m_cs.getStateValue(m_key, pendingStatePK);

        StateValue activeStateValue = new StateValue(id, Boolean.TRUE);
        activeStateValue.setNodeValue(new NodeValue(id, "Active", "The task is currently active.", "State", "State"));
        StatePK activeStatePK = m_cs.stateCreate(m_key, stateNodePK, activeStateValue);
        activeStateValue = m_cs.getStateValue(m_key, activeStatePK);

        StateValue inactiveStateValue = new StateValue(id, Boolean.FALSE);
        inactiveStateValue.setNodeValue(new NodeValue(id, "Inactive", "The task is not currently active.", "State", "State"));
        StatePK inactiveStatePK = m_cs.stateCreate(m_key, stateNodePK, inactiveStateValue);
        inactiveStateValue = m_cs.getStateValue(m_key, inactiveStatePK);

        StatusValue newStatusValue = new StatusValue(id);
        newStatusValue.setNodeValue(new NodeValue(id, "New", "The task is new and has just left the start state.", "Status", "Status"));
        StatusPK newStatusPK = m_cs.statusCreate(m_key, statusNodePK, newStatusValue);
        newStatusValue = m_cs.getStatusValue(m_key, newStatusPK);
        
        StatusValue startedStatusValue = new StatusValue(id);
        startedStatusValue.setNodeValue(new NodeValue(id, "Started", "The task has left the Pending state and entered the Active state.", "Status", "Status"));
        StatusPK startedStatusPK = m_cs.statusCreate(m_key, statusNodePK, startedStatusValue);
        startedStatusValue = m_cs.getStatusValue(m_key, startedStatusPK);
        
        StatusValue abandonedStatusValue = new StatusValue(id);
        abandonedStatusValue.setNodeValue(new NodeValue(id, "Abandoned", "The task has reverted to the Start State without being completed.", "Status", "Status"));
        StatusPK abandonedStatusPK = m_cs.statusCreate(m_key, statusNodePK, abandonedStatusValue);
        abandonedStatusValue = m_cs.getStatusValue(m_key, abandonedStatusPK);
        
        StatusValue suspendedStatusValue = new StatusValue(id);
        suspendedStatusValue.setNodeValue(new NodeValue(id, "Suspended", "The task has been moved from the Active to the Inactive state.", "Status", "Status"));
        StatusPK suspendedStatusPK = m_cs.statusCreate(m_key, statusNodePK, suspendedStatusValue);
        suspendedStatusValue = m_cs.getStatusValue(m_key, suspendedStatusPK);
        
        StatusValue resumedStatusValue = new StatusValue(id);
        resumedStatusValue.setNodeValue(new NodeValue(id, "Resumed", "The task has been moved from the Inactive to the Active state.", "Status", "Status"));
        StatusPK resumedStatusPK = m_cs.statusCreate(m_key, statusNodePK, resumedStatusValue);
        resumedStatusValue = m_cs.getStatusValue(m_key, resumedStatusPK);
        
        StatusValue completedStatusValue = new StatusValue(id);
        completedStatusValue.setNodeValue(new NodeValue(id, "Completed", "The task has reverted to the Start State after being successfully completed.", "Status", "Status"));
        StatusPK completedStatusPK = m_cs.statusCreate(m_key, statusNodePK, completedStatusValue);
        completedStatusValue = m_cs.getStatusValue(m_key, completedStatusPK);
        
        TaskStateMachineValue basicTaskTypeValue = new TaskStateMachineValue(id);
        basicTaskTypeValue.setNodeValue(new NodeValue(id, "Basic Task", "This state machine can typically be used for projects and actions.", "TaskStateMachine", "TaskStateMachine"));
        TaskStateMachinePK basicTaskTypePK = m_cs.taskStateMachineCreate(m_key, taskTypeNodePK, basicTaskTypeValue);
        basicTaskTypeValue = m_cs.getTaskStateMachineValue(m_key, basicTaskTypePK);
        TransitionValue transition1 = basicTaskTypeValue.getTransitionValues()[0];
        transition1.setSourceStateValue(startStateValue);
        transition1.setDestinationStateValue(pendingStateValue);
        transition1.setStatusValue(newStatusValue);
        transition1.setIsOwnerResponsible(Boolean.FALSE);
        transition1.setIsUserResponsible(Boolean.FALSE);
        basicTaskTypeValue.updateTransitionValue(transition1);
        TransitionValue transition2 = new TransitionValue(id, Boolean.FALSE, Boolean.FALSE);
        transition2.setSourceStateValue(pendingStateValue);
        transition2.setDestinationStateValue(startStateValue);
        transition2.setStatusValue(abandonedStatusValue);
        basicTaskTypeValue.addTransitionValue(transition2);
        TransitionValue transition3 = new TransitionValue(id, Boolean.FALSE, Boolean.FALSE);
        transition3.setSourceStateValue(pendingStateValue);
        transition3.setDestinationStateValue(activeStateValue);
        transition3.setStatusValue(startedStatusValue);
        basicTaskTypeValue.addTransitionValue(transition3);
        TransitionValue transition4 = new TransitionValue(id, Boolean.FALSE, Boolean.FALSE);
        transition4.setSourceStateValue(activeStateValue);
        transition4.setDestinationStateValue(inactiveStateValue);
        transition4.setStatusValue(suspendedStatusValue);
        basicTaskTypeValue.addTransitionValue(transition4);
        TransitionValue transition5 = new TransitionValue(id, Boolean.FALSE, Boolean.FALSE);
        transition5.setSourceStateValue(activeStateValue);
        transition5.setDestinationStateValue(startStateValue);
        transition5.setStatusValue(completedStatusValue);
        basicTaskTypeValue.addTransitionValue(transition5);
        TransitionValue transition6 = new TransitionValue(id, Boolean.FALSE, Boolean.FALSE);
        transition6.setSourceStateValue(inactiveStateValue);
        transition6.setDestinationStateValue(activeStateValue);
        transition6.setStatusValue(resumedStatusValue);
        basicTaskTypeValue.addTransitionValue(transition6);
        TransitionValue transition7 = new TransitionValue(id, Boolean.FALSE, Boolean.FALSE);
        transition7.setSourceStateValue(inactiveStateValue);
        transition7.setDestinationStateValue(startStateValue);
        transition7.setStatusValue(abandonedStatusValue);
        basicTaskTypeValue.addTransitionValue(transition7);
        m_cs.taskStateMachineEdit(m_key, basicTaskTypePK, basicTaskTypeValue);
    }
    
     public void setupRoles(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue roleNodeValue = new NodeValue(id, "Setup Roles", "The root node for all roles", "Node", "SystemNode");
        NodePK roleNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, roleNodeValue, "SystemNode");
        
        // move default role to the correct place
        RoleValue[] roleValues = m_cs.getAllRoleValues(m_key);
        for(int i = 0; i < roleValues.length; i++) {
            RoleValue roleValue = roleValues[i];
            if (roleValue.getNodeValue().getName().equals("Default Setup"))
                m_cs.moveChildNode(m_key, roleNodePK, roleValue.getNodeValue().getPrimaryKey());
        }
    }
    
     public void setupContactDetailTypes(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue contactNodeValue = new NodeValue(id, "Setup Contact Detail Types", "", "Node", "ContactDetailTypes");
        NodePK contactNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, contactNodeValue, "ContactDetailTypes");
    }
    
     public void setupSystemProperties(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue propertyNodeValue = new NodeValue(id, "Setup System Properties", "", "Node", "SystemProperties");
        NodePK propertyNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, propertyNodeValue, "SystemProperties");
    }
    
     public void setupLicenceManagement(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue propertyNodeValue = new NodeValue(id, "Licence Management", "", "Node", "LicenceManagement");
        NodePK propertyNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, propertyNodeValue, "LicenceManagement");
    }
   
     public void setupLoginHistory(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
        Integer id = new Integer(0);

        NodeValue propertyNodeValue = new NodeValue(id, "Login History", "", "Node", "LoginHistory");
        NodePK propertyNodePK = m_cs.nodeCreate(m_key, systemConfigNodePK, propertyNodeValue, "LoginHistory");
    }
   
     public void setupDirectory(NodePK systemConfigNodePK) throws RemoteException, FinderException, NamingException, CreateException, PermissionDeniedException, InvalidKeyException {
         NodePK nodePK = m_cs.findDirectoryNode(m_key);
         m_cs.moveChildNode(m_key, systemConfigNodePK, nodePK);
    }
   
    public static void setupDatabase(String p_username, String p_password) {
        try {
            SetupDatabase setup = new SetupDatabase(p_username, p_password);
            if (setup.getProceed()) {
                setup.login(p_username, p_password);
                setup.setupProjects();
                setup.setupSystemConfig(p_username);
                setup.logout();
            }
        } catch(Exception e){
            e.printStackTrace();
        }
    }
    
}
